const express = require("express");
const jwt = require("jsonwebtoken");
const { Op } = require("sequelize");
const User = require("../models/User");
const { body, validationResult } = require("express-validator");
const auth = require("../middleware/auth");
const https = require("https");
const url = require("url");
const crypto = require("crypto");

const router = express.Router();

// @route   POST /api/auth/wechat-login
// @desc    WeChat Mini Program login
// @access  Public
router.post(
  "/wechat-login",
  [body("code").notEmpty().withMessage("WeChat code is required")],
  async (req, res, next) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          message: "Validation failed",
          errors: errors.array(),
        });
      }

      const { code } = req.body;

      // 从环境变量获取微信小程序配置
      const appId = process.env.WECHAT_APP_ID;
      const appSecret = process.env.WECHAT_APP_SECRET;
      console.log(
        "Received code:",
        code,
        "appId:",
        appId,
        "appSecret:",
        appSecret
      );
      if (!appId || !appSecret) {
        return res.status(500).json({
          success: false,
          message: "WeChat configuration missing",
        });
      }

      // 调用微信API，使用code换取openid和session_key
      const wxApiUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${appSecret}&js_code=${code}&grant_type=authorization_code`;

      // 使用https模块发送请求
      const wxResponse = await new Promise((resolve, reject) => {
        const parsedUrl = url.parse(wxApiUrl);
        const options = {
          hostname: parsedUrl.hostname,
          path: parsedUrl.path,
          method: "GET",
        };

        const req = https.request(options, (res) => {
          let data = "";
          res.on("data", (chunk) => {
            data += chunk;
          });
          res.on("end", () => {
            try {
              const jsonData = JSON.parse(data);
              resolve(jsonData);
            } catch (error) {
              reject(error);
            }
          });
        });

        req.on("error", (error) => {
          reject(error);
        });

        req.end();
      });

      // 检查微信API响应
      if (wxResponse.errcode) {
        return res.status(400).json({
          success: false,
          message: "WeChat API error",
          error: wxResponse.errmsg,
        });
      }

      const { openid, session_key, unionid } = wxResponse;

      // 查找或创建用户
      let user = await User.findOne({ where: { openId: openid } });

      if (!user) {
        // 创建新用户，使用默认值
        user = await User.create({
          openId: openid,
          unionId: unionid || null,
          nickname: "微信用户", // 默认昵称
          avatarUrl: "https://picsum.photos/200/200?random=1", // 默认头像
          gender: 0, // 默认性别
          sessionKey: session_key,
          lastLoginAt: new Date(),
          lastLoginIP: req.ip,
        });
      } else {
        // 更新现有用户的session key和登录信息
        user.sessionKey = session_key;
        if (unionid) user.unionId = unionid;
        user.lastLoginAt = new Date();
        user.lastLoginIP = req.ip;

        await user.save();
      }

      // 生成JWT token
      const token = jwt.sign(
        {
          userId: user.id,
          openId: user.openId,
          unionId: user.unionId,
        },
        process.env.JWT_SECRET,
        { expiresIn: process.env.JWT_EXPIRE || "7d" }
      );

      // 更新用户的JWT token
      user.jwtToken = token;
      await user.save();

      res.json({
        success: true,
        message: "Login successful",
        data: {
          token,
          user: user.getPublicProfile(),
          isNewUser:
            !user.createdAt ||
            user.createdAt.getTime() === user.updatedAt.getTime(),
          needProfileUpdate: !user.nickname || user.nickname === "微信用户", // 标记是否需要更新用户信息
        },
      });
    } catch (error) {
      console.error("WeChat login error:", error);
      next(error);
    }
  }
);

// @route   POST /api/auth/wechat-decrypt
// @desc    Decrypt WeChat user info
// @access  Private
router.post(
  "/wechat-decrypt",
  [
    auth,
    body("encryptedData").notEmpty().withMessage("Encrypted data is required"),
    body("iv").notEmpty().withMessage("IV is required"),
  ],
  async (req, res, next) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          message: "Validation failed",
          errors: errors.array(),
        });
      }

      const { encryptedData, iv } = req.body;

      // 获取当前用户的session_key
      const user = await User.findByPk(req.user.userId);
      if (!user || !user.sessionKey) {
        return res.status(400).json({
          success: false,
          message: "Invalid session or session key missing",
        });
      }

      // 解密微信用户数据
      const sessionKey = user.sessionKey;
      const decipher = crypto.createDecipheriv(
        "aes-128-cbc",
        Buffer.from(sessionKey, "base64"),
        Buffer.from(iv, "base64")
      );

      let decrypted = decipher.update(encryptedData, "base64", "utf8");
      decrypted += decipher.final("utf8");

      const userInfo = JSON.parse(decrypted);

      // 更新用户信息
      if (userInfo.nickName) user.nickname = userInfo.nickName;
      if (userInfo.avatarUrl) user.avatarUrl = userInfo.avatarUrl;
      if (userInfo.gender !== undefined) user.gender = userInfo.gender;
      if (userInfo.city || userInfo.province || userInfo.country) {
        user.location = {
          city: userInfo.city || "",
          province: userInfo.province || "",
          country: userInfo.country || "",
        };
      }

      await user.save();

      res.json({
        success: true,
        message: "User info updated successfully",
        data: {
          user: user.getPublicProfile(),
        },
      });
    } catch (error) {
      console.error("WeChat decrypt error:", error);
      res.status(400).json({
        success: false,
        message: "Failed to decrypt user info",
        error: error.message,
      });
    }
  }
);
// @route   POST /api/auth/register
// @desc    Register new user (alternative to WeChat login)
// @access  Public
router.post(
  "/register",
  [
    body("nickname").notEmpty().withMessage("Nickname is required"),
    body("nickname")
      .isLength({ min: 2, max: 50 })
      .withMessage("Nickname must be between 2 and 50 characters"),
    body("email")
      .optional()
      .isEmail()
      .withMessage("Please provide a valid email"),
    body("phone")
      .optional()
      .matches(/^1[3-9]\d{9}$/)
      .withMessage("Please provide a valid Chinese phone number"),
  ],
  async (req, res, next) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          message: "Validation failed",
          errors: errors.array(),
        });
      }

      const { nickname, email, phone, bio, gender } = req.body;

      // Check if user already exists
      const existingUser = await User.findOne({
        where: {
          [Op.or]: [{ email }, { phone }],
        },
      });

      if (existingUser) {
        return res.status(400).json({
          success: false,
          message: "User with this email or phone already exists",
        });
      }

      // Create new user
      const user = await User.create({
        nickname,
        email,
        phone,
        bio: bio || "",
        gender: gender || 0,
        lastLoginAt: new Date(),
        lastLoginIP: req.ip,
      });

      // Generate JWT token
      const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, {
        expiresIn: process.env.JWT_EXPIRE || "7d",
      });

      user.jwtToken = token;
      await user.save();

      res.status(201).json({
        success: true,
        message: "User registered successfully",
        data: {
          token,
          user: user.getPublicProfile(),
        },
      });
    } catch (error) {
      next(error);
    }
  }
);

// @route   POST /api/auth/login
// @desc    Login user (alternative to WeChat login)
// @access  Public
router.post(
  "/login",
  [
    body("email").notEmpty().withMessage("Email is required"),
    body("password").notEmpty().withMessage("Password is required"),
  ],
  async (req, res, next) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          message: "Validation failed",
          errors: errors.array(),
        });
      }

      const { email, password } = req.body;

      // Find user by email
      const user = await User.findOne({ where: { email } });
      if (!user) {
        return res.status(401).json({
          success: false,
          message: "Invalid credentials",
        });
      }

      // For demo purposes, we'll skip password verification
      // In production, you should implement proper password hashing and verification

      // Update last login
      user.lastLoginAt = new Date();
      user.lastLoginIP = req.ip;

      // Generate JWT token
      const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, {
        expiresIn: process.env.JWT_EXPIRE || "7d",
      });

      user.jwtToken = token;
      await user.save();

      res.json({
        success: true,
        message: "Login successful",
        data: {
          token,
          user: user.getPublicProfile(),
        },
      });
    } catch (error) {
      next(error);
    }
  }
);

// @route   POST /api/auth/logout
// @desc    Logout user
// @access  Private
router.post("/logout", auth, async (req, res, next) => {
  try {
    const user = await User.findByPk(req.user.userId);
    if (user) {
      user.jwtToken = null;
      await user.save();
    }

    res.json({
      success: true,
      message: "Logged out successfully",
    });
  } catch (error) {
    next(error);
  }
});

// @route   GET /api/auth/me
// @desc    Get current user profile
// @access  Private
router.get("/me", auth, async (req, res, next) => {
  try {
    const user = await User.findByPk(req.user.userId);

    if (!user) {
      return res.status(404).json({
        success: false,
        message: "User not found",
      });
    }

    res.json({
      success: true,
      data: {
        user: user.getPublicProfile(),
      },
    });
  } catch (error) {
    next(error);
  }
});

// @route   PUT /api/auth/update-profile
// @desc    Update user profile
// @access  Private
router.put(
  "/update-profile",
  auth,
  [
    body("nickname")
      .optional()
      .notEmpty()
      .withMessage("Nickname cannot be empty"),
    body("nickname")
      .optional()
      .isLength({ min: 2, max: 50 })
      .withMessage("Nickname must be between 2 and 50 characters"),
    body("bio")
      .optional()
      .isLength({ max: 200 })
      .withMessage("Bio cannot exceed 200 characters"),
    body("phone")
      .optional()
      .matches(/^1[3-9]\d{9}$/)
      .withMessage("Please provide a valid Chinese phone number"),
    body("email")
      .optional()
      .isEmail()
      .withMessage("Please provide a valid email"),
  ],
  async (req, res, next) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({
          success: false,
          message: "Validation failed",
          errors: errors.array(),
        });
      }

      const {
        nickname,
        bio,
        avatarUrl,
        gender,
        phone,
        email,
        location,
        preferences,
      } = req.body;

      const user = await User.findByPk(req.user.userId);
      if (!user) {
        return res.status(404).json({
          success: false,
          message: "User not found",
        });
      }

      // Update fields if provided
      if (nickname !== undefined) user.nickname = nickname;
      if (bio !== undefined) user.bio = bio;
      if (avatarUrl !== undefined) user.avatarUrl = avatarUrl;
      if (gender !== undefined) user.gender = gender;
      if (phone !== undefined) user.phone = phone;
      if (email !== undefined) user.email = email;
      if (location !== undefined) user.location = location;
      if (preferences !== undefined) user.preferences = preferences;

      await user.save();

      res.json({
        success: true,
        message: "Profile updated successfully",
        data: {
          user: user.getPublicProfile(),
        },
      });
    } catch (error) {
      next(error);
    }
  }
);

// @route   POST /api/auth/refresh-token
// @desc    Refresh JWT token
// @access  Private
router.post("/refresh-token", auth, async (req, res, next) => {
  try {
    const user = await User.findByPk(req.user.userId);
    if (!user) {
      return res.status(404).json({
        success: false,
        message: "User not found",
      });
    }

    // Generate new token
    const newToken = jwt.sign(
      {
        userId: user.id,
        openId: user.openId,
        unionId: user.unionId,
      },
      process.env.JWT_SECRET,
      { expiresIn: process.env.JWT_EXPIRE || "7d" }
    );

    // Update user with new token
    user.jwtToken = newToken;
    await user.save();

    res.json({
      success: true,
      message: "Token refreshed successfully",
      data: {
        token: newToken,
      },
    });
  } catch (error) {
    next(error);
  }
});

module.exports = router;
